/*
 * @Author: wangming
 * @Date: 2021-09-13 18:10:53
 * @LastEditors: wangming
 * @LastEditTime: 2022-07-20 17:41:05
 * @FilePath: /hanma-paas-mobile-fed/Users/wm/瀚川/hanma-application-designer-fed/src/utils/mqttConfig.js
 * @Description: 
 */
import mqtt from "mqtt";
import { getHmmqttInfoByMqttKey, getHmmqttBuiltinconfig } from '@/apis/paas/HmMqttLinkController.js'
const mqttConfig = {
  keepalive: 60,
  clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
  protocolId: 'MQTT',
  path: '/mqtt',
  // protocolVersion: 4,
  connectTimeout: 40000,
  clean: true
}

class Appmqtt {
  constructor(host, username, password) {
    //是否有主题被使用
    this.topicRuning = false
    this.mqttEvents = {}
    this.subscribeList = []
    this.mqttClient = null
    this.url = "ws://" + host + ":8083/mqtt";
    this.username = username
    this.password = password
  }
  endMqtt() {
    this.mqttClient && this.mqttClient.end()
  }
  resetMqtt() {
    this.mqttEvents = {}
    this.subscribeList = []
    this.mqttClient = null
  }
  async initMqtt() {
    const cfg = Object.assign(mqttConfig, {
      port: '8083',
      username: this.username,
      password: this.password,
    });
    const client = mqtt.connect(this.url, cfg);
    // 建立连接后订阅主题
    return new Promise((resolve, reject) => {
      client.on("connect", () => {
        console.log("连接成功！！！");
        this.mqttClient = client
        this.subscribeList.forEach(i => {
          this.runMqtt(i.topic, i.key, i.callback)
        })
        resolve()
      });
      // 后台发送的消息
      client.on("message", (topic, message) => {
        var str = message.toString()
        // console.log(str, topic)
        try {
          str = JSON.parse(str)
        } catch (error) {
          console.log(error)
        }
        let mqttList = this.mqttEvents[topic] || []
        mqttList.forEach(({ callback }) => {
          callback(str)
        })
      });
      // 其他异常事件
      client.on("reconnect", (error) => {
        console.info("正在重连", error);
      });
      client.on("disconnect", (error) => {
        reject()
        client.end();
        console.info("服务器断开:", error);
        this.resetMqtt()
      });
      client.on("close", (error) => {
        reject()
        client.end();
        this.resetMqtt()
        console.info("服务器g关闭:", error);
      });
      client.on("error", (error) => {
        reject()
        console.log("连接失败！！！", error);
        client.end();
        this.resetMqtt()
      });
    })
  }
  async runMqtt(topic, key, callback) {
    this.mqttClient.subscribe(topic, { qos: 1 }, (err) => {
      if (!err) {
        if (!!this.mqttEvents[topic]) {
          this.mqttEvents[topic].push({ callback, key })
        } else {
          this.mqttEvents[topic] = [{ callback, key }]
        }
        this.topicRuning = true
        console.info(topic, " ---- 订阅成功");
      } else {
        console.warn("订阅失败");
      }
    });
  }
  subscribeMqtt(topic, key, callback) {
    if (!topic) return
    if (this.mqttClient) {
      this.runMqtt(topic, key, callback)
    } else {
      !this.subscribeList.length && this.initMqtt()
      this.subscribeList.push({ topic, key, callback })
    }
  }
  unsubscribeMqtt(topic, key) {
    if (!this.mqttClient || !topic) return
    let topicmqtt = this.mqttEvents[topic] || []
    if (topicmqtt?.length > 0) {
      this.mqttEvents[topic] = this.mqttEvents[topic].filter(i => i.key !== key)
    }
    if (!this.mqttEvents[topic]?.length) {
      this.mqttClient.unsubscribe(topic)
      this.mqttEvents[topic] = null
      let _mque = Object.values(this.mqttEvents).filter(i => !!i)
      !!_mque.length || (this.topicRuning = false)
      // console.log('取消订阅', topic)
    }
  }
}

export default class ServerMqtt {
  static subscribeServes = []
  //mqtt实例队列
  static serveQue = {}
  //清除掉队列
  static clearQue = {}
  //全局默认服务
  static msgWebconfig = null
  static async initAsyncServe(mqttKey) {
    if (process.env.VUE_APP_USER === "ADMIN") return Promise.reject()
    var instance = this.serveQue[mqttKey]
    if (!instance) {
      instance = this.getMqtt(mqttKey)
      this.serveQue[mqttKey] = instance
    }
    //清空计时器
    let timer = this.clearQue[mqttKey]
    if (!!timer) {
      clearTimeout(timer)
      this.clearQue[mqttKey] = null
      // console.log('执行了清空计时器的操作')
    }
    return instance
  }
  static async getMqtt(mqttKey) {
    let { mqttSettings } = await getHmmqttInfoByMqttKey({ mqttKey })
    let { host, username, password } = mqttSettings[0] || {}
    return new Appmqtt(host, username, password)

  }
  static async getDefaultMqtt() {
    if (process.env.VUE_APP_USER === "ADMIN") return Promise.reject()
    if (!!this.msgWebconfig) return this.msgWebconfig
    const config = (await getHmmqttBuiltinconfig()) || {};
    const { status, host, username, password } = config;
    if (status !== 1 || !host) return Promise.reject()
    this.msgWebconfig = new Appmqtt(host, username, password)
    return this.msgWebconfig
  }
  static async clearMqtt(mqttKey, topic, Modulekey) {
    if (process.env.VUE_APP_USER === "ADMIN") return
    var instance = await this.serveQue[mqttKey]
    if (instance) {
      instance.unsubscribeMqtt(topic, Modulekey)
      if (!instance.topicRuning) {
        this.destroyedMqtt(mqttKey, instance)
      }
    }
  }
  static destroyedMqtt(mqttKey, instance) {
    if (!!instance) {
      this.clearQue[mqttKey] = setTimeout(() => {
        instance.endMqtt()
        this.serveQue[mqttKey] = null
        this.clearQue[mqttKey] = null
        // console.log('执行了销毁服务的操作')
      }, 60000 * 5)
    }
  }
}

